package com.runnor.common.websys.system.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author runnor-yh
 * @date 2023年08月22日 11:26
 */
@RequestMapping("api/editor")
@RestController
public class EditorController {
    @Value("${app.uploadBase}")
    private String uploadBase;


    @RequestMapping
    public Object ueditor(HttpServletRequest request, MultipartFile file, String callback, String action) throws IOException {
        String yyyyMM = new SimpleDateFormat("yyyyMM").format(new Date());

        switch (action) {
            case "config":
                return createConfig();
            case "image":
                // 图片文件上传
                String imgName = file.getOriginalFilename();
                String imgSuffix = imgName.substring(imgName.lastIndexOf("."));
                String distImgFileName = uploadBase + "/picture/" + yyyyMM + "/" + DigestUtil.md5Hex(file.getInputStream()) + imgSuffix;
                File imgPath = new File(uploadBase + "/picture/" + yyyyMM);
                if (!imgPath.exists()) imgPath.mkdir();
                file.transferTo(new File(distImgFileName));
                JSONObject imgResult = new JSONObject();
                imgResult.putOpt("state", "SUCCESS");
                imgResult.putOpt("url", "/upload" + "/picture/" + yyyyMM + "/" + DigestUtil.md5Hex(file.getInputStream()) + imgSuffix);
                imgResult.putOpt("title", file.getOriginalFilename());
                imgResult.putOpt("original", file.getOriginalFilename());
                imgResult.putOpt("code", 200);
                imgResult.putOpt("data", new JSONObject() {{
                    this.putOpt("url", "/upload" + "/picture/" + yyyyMM + "/" + DigestUtil.md5Hex(file.getInputStream()) + imgSuffix);
                }});
                return imgResult;
            case "listImage":
                JSONObject imgListResult = new JSONObject();
                List<File> imgs = FileUtil.loopFiles(uploadBase + "/picture/");
                String imgSize = request.getParameter("size");
                String imgStart = request.getParameter("start");
                List<File> subImgList = imgs.subList(Integer.valueOf(imgStart), (Integer.valueOf(imgStart) + Integer.valueOf(imgSize)) > imgs.size() ? imgs.size() : (Integer.valueOf(imgStart) + Integer.valueOf(imgSize)));
                List<JSONObject> imgCollect = subImgList.stream().map(f -> new JSONObject() {{
                            this.putOpt("url", f.getAbsolutePath().replace(f.getParentFile().getParent(), "/upload/picture").replace("\\", "/"));
                        }}
                ).collect(Collectors.toList());
                imgListResult.putOpt("state", "SUCCESS");
                imgListResult.putOpt("list", imgCollect);
                imgListResult.putOpt("total", imgs.size());
                imgListResult.putOpt("start", Integer.valueOf(imgStart));
                return imgListResult;
            case "video":
                String videoName = file.getOriginalFilename();
                String videoSuffix = videoName.substring(videoName.lastIndexOf("."));
                String distVideoFileName = uploadBase + "/video/" + yyyyMM + "/" + DigestUtil.md5Hex(file.getInputStream()) + videoSuffix;
                File videoPath = new File(uploadBase + "/video/" + yyyyMM);
                if (!videoPath.exists()) videoPath.mkdir();
                file.transferTo(new File(distVideoFileName));
                JSONObject videoResult = new JSONObject();
                videoResult.putOpt("state", "SUCCESS");
                videoResult.putOpt("url", "/upload" + "/video/" + yyyyMM + "/" + DigestUtil.md5Hex(file.getInputStream()) + videoSuffix);
                videoResult.putOpt("title", file.getOriginalFilename());
                videoResult.putOpt("original", file.getOriginalFilename());
                return videoResult;
            case "file":
                String fileName = file.getOriginalFilename();
                String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
                String distFileName = uploadBase + "/attachment/" + yyyyMM + "/" + DigestUtil.md5Hex(file.getInputStream()) + fileSuffix;
                File filePath = new File(uploadBase + "/attachment/" + yyyyMM);
                if (!filePath.exists()) filePath.mkdir();
                file.transferTo(new File(distFileName));
                JSONObject fileResult = new JSONObject();
                fileResult.putOpt("state", "SUCCESS");
                fileResult.putOpt("url", "/upload" + "/attachment/" + yyyyMM + "/" + DigestUtil.md5Hex(file.getInputStream()) + fileSuffix);
                fileResult.putOpt("title", file.getOriginalFilename());
                fileResult.putOpt("original", file.getOriginalFilename());
                return fileResult;
            case "listFile":
                // 文件列表
                JSONObject fileListResult = new JSONObject();
                List<File> files = FileUtil.loopFiles(uploadBase + "/attachment/");
                String fileSize = request.getParameter("size");
                String fileStart = request.getParameter("start");
                List<File> subFileList = files.subList(Integer.valueOf(fileStart), (Integer.valueOf(fileStart) + Integer.valueOf(fileSize)) > files.size() ? files.size() : (Integer.valueOf(fileStart) + Integer.valueOf(fileSize)));
                List<JSONObject> fileCollect = subFileList.stream().map(f -> new JSONObject() {{
                            this.putOpt("url", f.getAbsolutePath().replace(f.getParentFile().getParent(), "/upload/attachment").replace("\\", "/"));
                        }}
                ).collect(Collectors.toList());
                fileListResult.putOpt("state", "SUCCESS");
                fileListResult.putOpt("list", fileCollect);
                fileListResult.putOpt("total", files.size());
                fileListResult.putOpt("start", Integer.valueOf(fileStart));
                return fileListResult;
            case "crawl":
                // 涂鸦上传(前台无此功能，暂不实现)
                return null;
            case "catch":
                // 图片抓取
                // output(['state' => '上传错误信息']);
//                $list = [];
//                $source = @$_POST['source'];
//                if (!is_array($source) || empty($source)) {
//                    $source = [];
//                }
//                foreach ($source as $imgUrl) {
//                $list[] = [
//                'state' => 'SUCCESS',
//                        'url' => 'https://ms-assets.modstart.com/demo/modstart.jpg',
//                        'size' => 100,
//                        'title' => 'title',
//                        'original' => '',
//                        'source' => htmlspecialchars($imgUrl),
//            ];
//            }
//            output(['state' => 'SUCCESS', 'list' => $list]);
//
            default:
                return null;
        }
    }

    private JSONObject createConfig() {
        JSONObject config = new JSONObject();
        // 执行上传图片的action名称，默认值：uploadimage
        config.putOpt("imageActionName", "image");
        // 提交的图片表单名称，默认值：upfile
        config.putOpt("imageFieldName", "file");
        // 上传大小限制，单位B，默认值：2048000
        config.putOpt("imageMaxSize", 2048000);
        // 上传图片格式显示，默认值：[".png", ".jpg", ".jpeg", ".gif", ".bmp"]
        config.putOpt("imageAllowFiles", new String[]{".jpg", ".png", ".jpeg", ".gif"});
        // 是否压缩图片,默认是true
        config.putOpt("imageCompressEnable", false);
        // 图片压缩最长边限制，默认值：1600
        config.putOpt("imageCompressBorder", 1600);
        // 插入的图片浮动方式，默认值：none
        config.putOpt("imageInsertAlign", "none");
        // 图片访问路径前缀，默认值：空
        config.putOpt("imageUrlPrefix", "");
        // 执行上传涂鸦的action名称，默认值：uploadscrawl
        config.putOpt("scrawlActionName", "crawl");
        // 提交的图片表单名称，默认值：upfile
        config.putOpt("scrawlFieldName", "file");
        // 上传大小限制，单位B，默认值：2048000
        config.putOpt("scrawlMaxSize", 2048000);
        // 图片访问路径前缀，默认值：空
        config.putOpt("scrawlUrlPrefix", "");
        // 插入的图片浮动方式，默认值：none
        config.putOpt("scrawlInsertAlign", "none");
        // 执行上传截图的action名称，默认值：uploadimage
        config.putOpt("snapscreenActionName", "snap\",");
        // 图片访问路径前缀
        config.putOpt("snapscreenUrlPrefix", "");
        // 插入的图片浮动方式，默认值：none
        config.putOpt("snapscreenInsertAlign", "none");
        // 例外的图片抓取域名
        config.putOpt("catcherLocalDomain", new String[]{"127.0.0.1", "localhost"});
        // 执行抓取远程图片的action名称，默认值：catchimage
        config.putOpt("catcherActionName", "catch");
        // 提交的图片列表表单名称，默认值：source
        config.putOpt("catcherFieldName", "source");
        // 图片访问路径前缀，默认值：空
        config.putOpt("catcherUrlPrefix", "");
        // 上传保存路径,可以自定义保存路径和文件名格式，默认值：{filename}{rand:6}
        config.putOpt("catcherMaxSize", 10485760);
        // 抓取图片格式显示，默认值：[".png", ".jpg", ".jpeg", ".gif", ".bmp"]
        config.putOpt("catcherAllowFiles", new String[]{".jpg", ".png", ".jpeg", ".gif"});
        // 执行上传视频的action名称，默认值：uploadvideo
        config.putOpt("videoActionName", "video");
        // 提交的视频表单名称，默认值：upfile
        config.putOpt("videoFieldName", "file");
        // 视频访问路径前缀
        config.putOpt("videoUrlPrefix", "");
        // 上传大小限制，单位B，默认值：102400000
        config.putOpt("videoMaxSize", 102400000);
        // 上传视频格式显示
        config.putOpt("videoAllowFiles", new String[]{".mp4", ".mkv"});
        // 执行上传文件的action名称，默认值：uploadfile
        config.putOpt("fileActionName", "file");
        // 提交的文件表单名称，默认值：upfile
        config.putOpt("fileFieldName", "file");
        // 文件访问路径前缀
        config.putOpt("fileUrlPrefix", "");
        // 上传保存路径,可以自定义保存路径和文件名格式，默认值：{filename}{rand:6}
        config.putOpt("fileMaxSize", 104857600);
        // 上传文件格式显示
//        config.putOpt("fileAllowFiles", new String[]{".zip", ".pdf", ".doc", ".xls", ".docx", ".xlsx", ".ppt", ".pptx"});
        config.putOpt("fileAllowFiles", new String[]{
                ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".webp",
                ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
                ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
                ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
                ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".log", ".md", ".xml", ".vsd", ".vsdx",
                ".sql", ".exe", ".jar", ".js", ".css"
        });
        // 执行图片管理的action名称，默认值：listimage
        config.putOpt("imageManagerActionName", "listImage");
        // 每次列出文件数量
        config.putOpt("imageManagerListSize", 20);
        // 图片访问路径前缀
        config.putOpt("imageManagerUrlPrefix", "");
        // 插入的图片浮动方式，默认值：none
        config.putOpt("imageManagerInsertAlign", "none");
        // 列出的文件类型
        config.putOpt("imageManagerAllowFiles", new String[]{".jpg", ".png", ".jpeg", ".gif"});
        // 执行文件管理的action名称，默认值：listfile
        config.putOpt("fileManagerActionName", "listFile");
        // 指定要列出文件的目录
        config.putOpt("fileManagerUrlPrefix", "");
        // 每次列出文件数量
        config.putOpt("fileManagerListSize", 20);
        // 列出的文件类型
//        config.putOpt("fileManagerAllowFiles", new String[]{".zip", ".pdf", ".doc", ".xls", ".docx", ".xlsx", ".ppt", ".pptx"});
        config.putOpt("fileManagerAllowFiles", new String[]{
                ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".webp",
                ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
                ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
                ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
                ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".log", ".md", ".xml", ".vsd", ".vsdx",
                ".sql", ".exe", ".jar", ".js", ".css"
        });
        // 公式配置
//        config.putOpt("formulaConfig", new JSONObject().putOpt("imageUrlTemplate", "https://latex.codecogs.com/svg.image?{}"));
        return config;
    }
}
